package com.cocotingo.snail.template.models;

import com.cocotingo.snail.template.TemplateSyntaxException;

public abstract class LayoutFactorNode extends Node {

	public static final int UNKNOWN = -1;
	
	public static final int LEFT = 0;
	public static final int RIGHT = 2;
	public static final int CENTER_LEFT = 1;
	public static final int WIDTH = 3;
	
	public static final int TOP = 4;
	public static final int BOTTOM = 6;
	public static final int CENTER_TOP = 5;
	public static final int HEIGHT = 7;
	
	private int factorType;

	public LayoutFactorNode() {
		this.factorType = UNKNOWN;
	}

	public int getFactorType() {
		return factorType;
	}

	public void setFactorType(int factorType) {
		this.factorType = factorType;
	}
	
	private static String getFactorTypeName(int factorType) {
		switch (factorType) {
		case LEFT: return "Left";
		case RIGHT: return "Right";
		case CENTER_LEFT: return "CenterLeft";
		case WIDTH: return "Width";
		case TOP: return "Top";
		case BOTTOM: return "Bottom";
		case CENTER_TOP: return "CenterTop";
		case HEIGHT: return "Height";
		default: return "Unknown";
		}
	}

	public boolean isHorizentalFactor() {
		return factorType >= 0 && factorType <= 3;
	}

	public boolean isVerticalFactor() {
		return factorType >= 4 && factorType <= 7;
	}
	
	protected boolean isValidFactorType(int factorType) {
		return factorType >= 0 && factorType <= 7;
	}

	@Override
	public void validateNode() throws TemplateSyntaxException {
		if (!isValidFactorType(factorType))
			throw new TemplateSyntaxException(this, "Illegal LayoutFactorNode.factorType: " + factorType + ".");
	}
	
	@Override
	public Iterable<Node> children() {
		return Node.EMPTY_ITERABLE;
	}
	
	public abstract int getLayoutType();
	
	@Override
	protected String getXMLNodeName() {
		return getFactorTypeName(factorType);
	}
	
	//// Concrete Classes ////
	
	public static final int LAYOUT_ABSOLUTE = 0;
	public static final int LAYOUT_REFERENCED = 1;
	public static final int LAYOUT_NEIGHBOR = 2;
	public static final int LAYOUT_FITTING = 3;
	public static final int LAYOUT_PREFERRED = 4;
	public static final int LAYOUT_CENTERED = 5;
	
	public static class AbsoluteLayoutFactorNode extends LayoutFactorNode {
		
		private String value;
		
		public String getValue() {
			return value;
		}
		
		public void setValue(String value) {
			this.value = value;
		}
		
		@Override
		public void validateNode() throws TemplateSyntaxException {
			super.validateNode();
			if (value == null || value.isEmpty()) throw new TemplateSyntaxException(this, "AbsoluteLayoutFactorNode.value shouldn't be empty/null.");
		}

		@Override
		public int getLayoutType() {
			return LAYOUT_ABSOLUTE;
		}

		@Override
		protected String getXMLAttributes() {
			return String.format("value=\"%s\"", value);
		}
		
	}

	public static class ReferencedLayoutFactorNode extends LayoutFactorNode {
		
		private String view;
		private String multiplier;
		
		public String getReferencedView() {
			return view;
		}
		
		public void setReferencedView(String view) {
			this.view = view;
		}
		
		public String getMultiplier() {
			return multiplier;
		}
		
		public void setMultiplier(String multiplier) {
			this.multiplier = multiplier;
		}
		
		@Override
		public void validateNode() throws TemplateSyntaxException {
			super.validateNode();
			if (view == null || view.isEmpty()) throw new TemplateSyntaxException(this, "ReferencedLayoutFactorNode.referencedView shouldn't be empty/null.");
		}

		@Override
		public int getLayoutType() {
			return LAYOUT_REFERENCED;
		}
		
		@Override
		protected String getXMLAttributes() {
			if (multiplier == null) {
				return String.format("reference=\"%s\"", view);
			} else {
				return String.format("reference=\"%s\" multiplier=\"%s\"", view, multiplier);
			}
		}
		
	}
	
	public static class NeighborLayoutFactorNode extends LayoutFactorNode {
		
		private String view;
		private String margin;
		
		public String getNeighborView() {
			return view;
		}
		
		public void setNeighborView(String view) {
			this.view = view;
		}
		
		public String getMargin() {
			return margin;
		}
		
		public void setMargin(String margin) {
			this.margin = margin;
		}
		
		@Override
		protected boolean isValidFactorType(int factorType) {
			return factorType == LEFT || factorType == RIGHT || factorType == TOP || factorType == BOTTOM;
		}
		
		@Override
		public void validateNode() throws TemplateSyntaxException {
			super.validateNode();
			if (view == null || view.isEmpty()) throw new TemplateSyntaxException(this, "NeighborLayoutFactorNode.neighborView shouldn't be empty/null.");
		}

		@Override
		public int getLayoutType() {
			return LAYOUT_NEIGHBOR;
		}
		
		@Override
		protected String getXMLAttributes() {
			if (margin == null) {
				return String.format("neighbor=\"%s\"", view);
			} else {
				return String.format("neighbor=\"%s\" margin=\"%s\"", view, margin);
			}
		}
		
	}

	public static class FittingLayoutFactorNode extends LayoutFactorNode {
		
		private String view;
		private String margin;
		
		public String getContentView() {
			return view;
		}
		
		public void setContentView(String view) {
			this.view = view;
		}
		
		public String getMargin() {
			return margin;
		}
		
		public void setMargin(String margin) {
			this.margin = margin;
		}
		
		@Override
		protected boolean isValidFactorType(int factorType) {
			return factorType == WIDTH || factorType == HEIGHT;
		}
		
		@Override
		public void validateNode() throws TemplateSyntaxException {
			super.validateNode();
			if (view == null || view.isEmpty()) throw new TemplateSyntaxException(this, "FittingLayoutFactorNode.contentView shouldn't be empty/null.");
		}

		@Override
		public int getLayoutType() {
			return LAYOUT_FITTING;
		}
		
		@Override
		protected String getXMLAttributes() {
			if (margin == null) {
				return String.format("content=\"%s\"", view);
			} else {
				return String.format("content=\"%s\" margin=\"%s\"", view, margin);
			}
		}
		
	}
	
	public static class PreferredLayoutFactorNode extends LayoutFactorNode {
		
		private int defaultValue;
		
		public int getDefaultValue() {
			return defaultValue;
		}
		
		public void setDefaultValue(int defaultValue) {
			this.defaultValue = defaultValue;
		}
		
		@Override
		protected boolean isValidFactorType(int factorType) {
			return factorType == WIDTH || factorType == HEIGHT;
		}
		
		@Override
		public int getLayoutType() {
			return LAYOUT_PREFERRED;
		}
		
		@Override
		protected String getXMLNodeName() {
			switch (getFactorType()) {
			case WIDTH: return "PreferredWidth";
			case HEIGHT: return "PreferredHeight";
			default: return "Unknown";
			}
		}
		
		@Override
		protected String getXMLAttributes() {
			return String.format("default=\"%d\"", defaultValue);
		}
		
	}
	
	public static class CenteredLayoutFactorNode extends LayoutFactorNode {
		
		@Override
		protected boolean isValidFactorType(int factorType) {
			return factorType == CENTER_LEFT || factorType == CENTER_TOP;
		}
		
		@Override
		public int getLayoutType() {
			return LAYOUT_CENTERED;
		}
		
		@Override
		protected String getXMLNodeName() {
			switch (getFactorType()) {
			case CENTER_LEFT: return "HorizontalCenter";
			case CENTER_TOP: return "VerticalCenter";
			default: return "Unknown";
			}
		}

		@Override
		protected String getXMLAttributes() {
			return null;
		}
		
	}
	
}
